Client/server computing has become more and more important over the past few years in the information technology world. This type of distributed computing allows one machine to delegate some of its work to another machine that might be, for example, better suited to perform that work. For example, the server could be a high-powered computer running a database program managing the storage of a vast amount of data, while the client is simply a desktop personal computer (PC) which requests information from the database to use in one of its local programs.
The benefits of client/server computing have been even further enhanced by the use of a well-known computer programming technology called object-oriented programming (OOP), which allows the client and server to be located on different (heterogeneous) "platforms". A platform is a combination of the specific hardware/software/operating system/communication protocol which a machine uses to do its work. OOP allows the client application program and server application program to operate on their own platforms without worrying how the client application's work requests will be communicated and accepted by the server application. Likewise, the server application does not have to worry about how the OOP system will receive, translate and send the server application's processing results back to the requesting client application.
Details of how OOP techniques have been integrated with heterogeneous client/server systems are explained in U.S. Pat. No. 5,440,744 and European Patent Application 0 677,943 A2. These latter two publications are hereby incorporated by reference. However, an example, of the basic architecture will be given below for contextual understanding of the invention's environment.
As shown in FIG. 1, the client computer 10 (which could, for example, be a personal computer having the IBM OS/2 operating system installed thereon) has an application program 40 running on its operating system ("IBM" and "OS/2" are trademarks of the International Business Machines corporation). The application program 40 will periodically require work to be performed on the server computer 20 and/or data to be returned from the server 20 for subsequent use by the application program 40. The server computer 20 can be, for example, a high-powered mainframe computer running on IBM's MVS operating system ("MVS" is also a trademark of the IBM corp.). For the purposes of the present invention it is irrelevant whether the requests for communications services to be carried out by the server are instigated by user interaction with the first application program 40, or whether the application program 40 operates independently of user interaction and makes the requests automatically during the running of the program.
When the client computer 10 wishes to make a request for the server computer 20's services, the first application program 40 informs the first logic means 50 of the service required. It may for example do this by sending the first logic means the name of a remote procedure along with a list of input and output parameters. The first logic means 50 then handles the task of establishing the necessary communications with the second computer 20 with reference to definitions of the available communications services stored in the storage device 60. All the possible services are defined as a cohesive framework of object classes 70, these classes being derived from a single object class. Defining the services in this way gives rise to a great number of advantages in terms of performance and reusability.
To establish the necessary communication with the server 20, the first logic means 50 determines which object class in the framework needs to be used, and then creates an instance of that object at the server, a message being sent to that object so as to cause that object to invoke one of its methods. This gives rise to the establishment of the connection with the server computer 20 via the connection means 80, and the subsequent sending of a request to the second logic means 90.
The second logic means 90 then passes the request on to the second application program 100 (hereafter called either the service or server application) running on the server computer 20 so that the service application 100 can perform the specific task required by that request, such as running a data retrieval procedure. Once this task has been completed the service application may need to send results back to the first computer 10. The service application 100 interacts with the second logic means 90 during the performance of the requested tasks and when results are to be sent back to the first computer 10. The second logic means 90 establishes instances of objects, and invokes appropriate methods of those objects, as and when required by the service application 100, the object instances being created from the cohesive framework of object classes stored in the storage device 110.
Using the above technique, the client application program 40 is not exposed to the communications architecture. Further the service application 100 is invoked through the standard mechanism for its environment; it does not know that it is being invoked remotely.
The Object Management Group (OMG) is an international consortium of organizations involved in various aspects of client/server computing on heterogeneous platforms with distributed objects as is shown in FIG. 1. The OMG has set forth published standards by which client computers (e.g. 10) communicate (in OOP form) with server machines (e.g. 20). As part of these standards, an Object Request Broker (ORB) has been defined, which provides the object-oriented bridge between the client and the server machines. The ORB decouples the client and server applications from the object oriented implementation details, performing at least part of the work of the first and second logic means 50 and 90 as well as the connection means 80. The ORB also handles all interactions amongst various server objects of the service application 100.
Computer implemented transaction processing systems are used for critical business tasks in a number of industries. A transaction defines a single unit of work that must either be fully completed or fully purged without action. For example, in the case of a bank automated teller machine from which a customer seeks to withdraw money, the actions of issuing the money, reducing the balance of money on hand in the machine and reducing the customer's bank balance must all occur or none of them must occur. Failure of one of the subordinate actions would lead to inconsistency between the records and the actual occurrences.
Distributed transaction processing involves a transaction that affects resources at more than one physical or logical location. In the above example, a transaction affects resources managed at the local automated teller machine (ATM) as well as bank balances managed by a bank's main computer. Such transactions involve one particular client computer (e.g, 10) communicating with one particular server computer (e.g., 20) over a series of client requests which are processed by the server.
In typical client/server systems, client and server systems are each contributing to the overall processing of such transactions. Further, many different clients may be concurrently attempting to use the same server to engage in separate transactions. For example, many different banking ATM machines (client systems) may be trying to concurrently begin transactions so as to access data from a popular database program running on the bank's large central server. Further, there are even many different intra-server requests (i.e., requests passing from one server object to another server object) which may be part of separate (concurrent) transactions. In these situations, the server must be able to isolate these concurrent transactions so that they do not affect each other. That is, until one transaction is finished (either all parts are committed or all parts are aborted) other transactions trying to access the same server objects must be made to wait. The server objects which are involved in a transaction must be locked while the transaction is pending. Locking prevents extra-transactional concurrent accesses to the server objects which would effect the present transaction.
For example, if a husband is trying to transfer $2000 from a family's checking account into the family's higher interest paying savings account at an ATM machine at one bank on one side of town and his wife is attempting to perform the same function at another ATM (owned by a different bank) on the other side of town, the server must be able to deal with this situation effectively so that the two concurrent transactions do not create a problem for the bank owning the database server.
The way this problem has typically been solved in the object oriented programming context is for the server database program (server or service application program 100) to be written so as to not only perform the substantive functions of the program but also to perform transactional locking on concurrent accesses. That is, the server application 100 would be written so that it would lock access to the family's account data stored in the database once a first client (e.g. the husband's ATM) requests access. Then, the husband's transaction would continue in isolation despite the fact that the wife's transaction has been requested concurrently. The wife's client ATM would not be granted access to the data because the husband's client ATM would already have a lock on the object encapsulating this data.
The way such concurrency control is presently done is as follows. Each request from a client that arrives at a server must first pass through a concurrency control gateway that analyzes the request and compares it to the requests which have previously been granted access to the server resources and are still, in fact, accessing such resources. The purpose of this comparison is to determine whether the new request is compatible with the previous (and still current) requests. If so, the new request can be allowed to pass through the concurrency control gateway. If not, the new request should wait until at least one of the previous requests is finished.
Assume one client has issued a request to add money to the balance of a particular checking account (the checking account is represented in the server by a checking account object). Assume also that no other client requests have attempted to gain access to this particular checking account object. The server software has received this request and, upon analyzing it, determined from the operation involved (adding money to the balance) that this request needs to have "write access" to the checking account object (since the adding operation requires that the state of the checking account object be changed to increase the balance). Since no other request has tried to gain access to this object, there is no concurrency problem with respect to other requests, so the request is simply sent to the target object for execution of the request.
Now, while this request has access to the target object, assume another client is making a concurrent request to check the account balance of the same checking account object. The server software determines from the operation involved (checking bank balance) that this request requires "read access" to the target object. The server software then checks in a table to determine whether this new request can be given access to the target object concurrently with the other request which already has "write access". The table stores yes/no scalar values for each combination of a small number (usually about five) of access modes (read access, write access etc.).
In this example, the new request would be found from the table to conflict with the previous request, since the "read access" request must wait until the "write access" request has finished writing, otherwise the "read access" request would give a different result based on whether the "write access" request has actually changed the data or not when the "read access" request reads the data. To avoid this, the "read access" request is made to wait until the "write access" request is completely finished and is no longer accessing the target object (the "write access" request is said to have a "write lock" on the target object).
Thus, conflict between concurrent requests in the known prior art has traditionally been determined by the concurrency control gateway examining the new client request (e.g. "check balance"), converting this request into one of a small number (e.g, five) of access modes (e.g., read) and then comparing this access mode with the access modes of the previous (and still current) requests. This concurrency control technique is sufficient when the operation (e.g., "check balance") associated with a request is simple and corresponds to only one access mode (e.g., read).
However, there are situations where the relationship between an operation and an access mode is not a simple one-to-one correspondence. There are also situations where this relationship can be made more complex in order to achieve greater efficiency and/or a reduction in deadlocks (where two requests are each waiting to next access a server resource that the other request currently holds). For example, when a target object is compound (it contains or refers to other objects), conflict resolution becomes complicated and, when the abovementioned conventional approach to concurrency control is used, results in a less than desirable compromise result, such as granting a request exclusive access to a group of objects when the request only need have exclusive access to a subset thereof.
Some prior art teachings have noted the problems associated with locking using only a small number (e.g., 5) of access modes, and have thus extended the number of predefined locking modes so that operations are mapped to a larger set of access modes. See, for example, A. Z. Spector et al, "Support for Distributed Transactions in the TABS Prototype", IEEE Transactions on Software Engineering, June 1985, pp. 521-2.
However, this latter prior art still operates with predefined access modes, albeit a larger set thereof. The mapping between operations and access modes is predetermined, and conflict checking is still done by comparing access modes. Because of this, greater than necessary exclusive access to server resources is still given to a particular lock requester, especially in the case of a server resource represented by a compound object.
In a more complex server resource, such as one associated with a compound object, conflict resolution should ideally be performed based on a plurality of factors. For example, a queue object contains six elements (each represented as a separate object). The queue object is non-empty because it contains six elements. A first client request is to remove the first element and a second client request is to add another (i.e., a seventh) element. Each request can run concurrently under separate transactions without compromising the integrity of the queue object. The granting of access permission depends on (a) the constantly changing state of the queue object (in this case, whether it is empty or not) and (b) the details of the two requests. If the queue were empty, both requests could not be given concurrent access, even if the requests themselves were inherently non-conflicting, since the request to remove an element could not take place if the queue were empty.
A second example is a non-empty array object (containing a plurality of elements as contained objects within the containing array object). A first request is to update an existing element of the array. A second request is to delete a different existing element. A third request is to add an element at a position in the array where no element exists. And, a fourth request is to delete an array element that exists but is neither the target of requests one nor two. Each request can run concurrently under its own transaction without compromising the integrity of the array or the work done in each of the other three transactions. Again, the granting of access permission for each request depends on the state of the array object and the details of that request in its relationship with the other three.
The above-mentioned conventional conflict resolution techniques, which operate by only comparing predefined access modes, have no way of taking into account a collection of such factors and can thus lead to undesirable concurrency control results.